/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package persistencia;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 *
 * @author Sebastian
 */
public class ExpertoPersistencia {

    private Statement stmt;
    private Connection conn;
    private static ExpertoPersistencia instancia;

    private ExpertoPersistencia() {
    }

    ;
    
    public static synchronized ExpertoPersistencia getInstancia() {
        if (instancia == null) {
            instancia = new ExpertoPersistencia();
        }
        return instancia;
    }

    //Bases de Datos soportadas
    public enum motorBD {

        Derby, MySQL, Postgres
    }

    /**
     * Metodo que realiza la conexión a la base de datos
     * @param nombreDB Nombre de la Base de Datos
     * @param usuario Nombre de Usuario registrado en la Base de datos
     * @param contrasenia Contraseña del usuario registrado en la Base de Datos
     * @param local Si la base de datos es local=true o remota=false
     * @param ipDB IP de la base de datos remota, en caso de ser local este parametro se ignora 
     * @param puertoDB Puerto en que la Base de Datos espera conexiones entrantes
     * @param motorDB Nombre del motor de la Base de Datos al que se quiere conectar
     * @return 
     */
    public Statement conectar(String nombreDB, String usuario, String contrasenia,
            boolean local, String dirIP, String puerto, String motorDB) {

        String url = crearURL(local, nombreDB, dirIP, puerto, motorDB);

        try {
            Class.forName(FabricaAdaptadorDB.getInstancia().obtenerAdaptadorDB(motorDB).getDriver()).newInstance();
            conn = DriverManager.getConnection(url, usuario, contrasenia);
            if (conn != null) {
                stmt = conn.createStatement();
            } else {
                stmt = null;
            }
        } catch (Exception e) {
            System.out.println("Error de conexión a la BD: " + e.toString());
        }
        return stmt;
    }

    /**
     * Metodo para realizar una desconexión ya establecida
     */
    public void desconectar() {
        if (conn != null && stmt != null) {
            try {
                stmt.close();
                conn.close();
            } catch (SQLException e) {
                System.out.println("Error en la desconexión de la BD: " + e.toString());
            }
        }
    }

    private String crearURL(boolean local, String nombreDB, String ip, String puerto, String motor) {
        String resultado = "jdbc:";
        if (motor.equals(motorBD.MySQL.name())) {
            resultado += "mysql:";
        } else if (motor.equals(motorBD.Postgres.name())) {
            resultado += "postgresql:";
        } else if (motor.equals(motorBD.Derby.name())) {
            resultado += "derby:";
        }

        if (local) {
            resultado += "//localhost";
        } else {
            resultado += "//" + ip;
        }
        resultado += ":" + puerto + "/";
        resultado += nombreDB;
        return resultado;
    }

    public ResultSet ejecutarConsulta(String consultaSQL) {
        ResultSet resultado = null;
        if (stmt == null) {
            System.out.println("Aun no se establece una conexion a la Base de Datos");
        } else {
            try {
                System.out.println("SQL: "+consultaSQL);
                resultado = stmt.executeQuery(consultaSQL);
            } catch (Exception e) {
                System.out.println("Error al ejecutar consulta SQL: " + e.toString());
            }
        }
        return resultado;
    }

    public boolean ejecutarSQL(String sQL) {
        boolean funciono = true;
        if (stmt == null) {
            System.out.println("Aun no se establece una conexion a la Base de Datos");
        } else {
            try {
                System.out.println("SQL: "+sQL);                
                funciono = stmt.execute(sQL);
            } catch (Exception e) {
                System.out.println("Error al ejecutar SQL: " + e.toString());
                funciono = false;
            }
        }
        return funciono;
    }

    public boolean ejecutarSQLABM(String sQL) {
        boolean funciono = true;
        if (stmt == null) {
            System.out.println("Aun no se establece una conexion a la Base de Datos");
        } else {
            try {
                System.out.println("SQL: "+sQL);   
                stmt.executeUpdate(sQL);
            } catch (Exception e) {
                System.out.println("Error al ejecutar SQL ABM: " + e.toString());
                funciono = false;
            }
        }
        return funciono;
    }

    public void inicializarBD() {
        try {
            ejecutarSQL("CREATE TABLE PACIENTE (oidPaciente VARCHAR(36) NOT NULL , codPaciente INTEGER NOT NULL, nombre VARCHAR(20) NOT NULL, apellido VARCHAR(20) NOT NULL, dni VARCHAR(20) NOT NULL, domicilio VARCHAR(40), fechaNacimiento TIMESTAMP, telefono VARCHAR(20), fechaAlta TIMESTAMP, contrasenia VARCHAR(20) , PRIMARY KEY (oidPaciente))");
            ejecutarSQL("CREATE TABLE ESTADO_FICHA_INTERNACION (oidEstadoFichaInternacion VARCHAR(36) NOT NULL, codEstadoFicha INTEGER NOT NULL, nombreEstadoFicha VARCHAR(20) NOT NULL, PRIMARY KEY (oidEstadoFichaInternacion))");
            ejecutarSQL("CREATE TABLE HABITACION (oidHabitacion VARCHAR(36) NOT NULL, disponible SMALLINT, nroHabitacion INTEGER, sector VARCHAR(20), tipoHabitacion VARCHAR(20), PRIMARY KEY (oidHabitacion))");
            ejecutarSQL("CREATE TABLE CAMA (oidCama VARCHAR(36) NOT NULL, libre SMALLINT, nroCama INTEGER, oidHabitacion VARCHAR(36), PRIMARY KEY (oidCama), FOREIGN KEY (oidHabitacion) REFERENCES HABITACION (oidHabitacion))");
            ejecutarSQL("CREATE TABLE ESTADO_PEDIDO (oidEstadoPedido VARCHAR(36) NOT NULL, codEstadoPedido INTEGER NOT NULL, nombreEstado VARCHAR(20) NOT NULL, PRIMARY KEY(oidEstadoPedido))");
            ejecutarSQL("CREATE TABLE DIA (oidDia VARCHAR(36) NOT NULL, nroDia INTEGER, nombreDia VARCHAR(20), PRIMARY KEY(oidDia))");
            ejecutarSQL("CREATE TABLE SERVICIO (oidServicio VARCHAR(36) NOT NULL, codServicio INTEGER, nombreServicio VARCHAR(20), tiempoDuracionUnitaria INTEGER, PRIMARY KEY(oidServicio))");
            ejecutarSQL("CREATE TABLE PRODUCTO (oidProducto VARCHAR(36) NOT NULL, codProducto INTEGER, marca VARCHAR(20), nombreProducto VARCHAR(20), descripcionProducto VARCHAR(40),cantidadDisponible INTEGER, bloqueado SMALLINT, PRIMARY KEY(oidProducto))");
            ejecutarSQL("CREATE TABLE PROMOCION (oidPromocion VARCHAR(36) NOT NULL, codPromocion INTEGER, nombrePromocion VARCHAR(100), fechaInicioVigencia TIMESTAMP, fechaFinVigencia TIMESTAMP, porcentajeDescuentoPorCantidad FLOAT, porcentajeDescuentoPorDia FLOAT, cantProductos INTEGER, oidProducto VARCHAR(36), oidDia VARCHAR(36), PRIMARY KEY(oidPromocion), FOREIGN KEY(oidProducto) REFERENCES PRODUCTO (oidProducto), FOREIGN KEY(oidDia) REFERENCES DIA (oidDia))");
            ejecutarSQL("CREATE TABLE FICHA_INTERNACION (oidFichaInternacion VARCHAR(36) NOT NULL, nroFicha INTEGER, fechaIngreso TIMESTAMP, fechaEgreso TIMESTAMP, oidPaciente VARCHAR(36), oidEstadoFichaInternacion VARCHAR(36), oidCama VARCHAR(36), oidHabitacion VARCHAR(36), PRIMARY KEY(oidFichaInternacion), FOREIGN KEY(oidPaciente) REFERENCES PACIENTE(oidPaciente), FOREIGN KEY(oidEstadoFichaInternacion) REFERENCES ESTADO_FICHA_INTERNACION (oidEstadoFichaInternacion), FOREIGN KEY (oidCama) REFERENCES CAMA (oidCama), FOREIGN KEY (oidHabitacion) REFERENCES HABITACION (oidHabitacion))");
            ejecutarSQL("CREATE TABLE PEDIDO (oidPedido VARCHAR(36) NOT NULL, nroPedido INTEGER, fechaIngreso TIMESTAMP, oidFichaInternacion VARCHAR(36) NOT NULL, oidEstadoPedido VARCHAR(36), PRIMARY KEY(oidPedido), FOREIGN KEY(oidFichaInternacion) REFERENCES FICHA_INTERNACION (oidFichaInternacion), FOREIGN KEY(oidEstadoPedido) REFERENCES ESTADO_PEDIDO (oidEstadoPedido))");
//            ejecutarSQL("CREATE TABLE INVENTARIO_STOCK (oidInventarioStock VARCHAR(36) NOT NULL, cantidadDisponible INTEGER, bloqueado SMALLINT, oidProducto VARCHAR(36), PRIMARY KEY(oidInventarioStock), FOREIGN KEY(oidProducto) REFERENCES PRODUCTO (oidProducto))");
            ejecutarSQL("CREATE TABLE EMPLEADO (oidEmpleado VARCHAR(36) NOT NULL, legajo INTEGER, nombre VARCHAR(20), apellido VARCHAR(20), disponible SMALLINT, bloqueado SMALLINT, oidServicio VARCHAR(36) , PRIMARY KEY(oidEmpleado), FOREIGN KEY(oidServicio) REFERENCES SERVICIO (oidServicio))");
            ejecutarSQL("CREATE TABLE DETALLE_PEDIDO_SERVICIO (oidDetallePedidoServicio VARCHAR(36) NOT NULL, descripcion VARCHAR(40), fechaHoraInicio TIMESTAMP, duracion INTEGER, importeSubtotal DOUBLE, oidPedido VARCHAR(36), oidEmpleado VARCHAR(36), oidServicio VARCHAR(36) NOT NULL, PRIMARY KEY(oidDetallePedidoServicio), FOREIGN KEY(oidPedido) REFERENCES PEDIDO (oidPedido), FOREIGN KEY(oidEmpleado) REFERENCES EMPLEADO (oidEmpleado), FOREIGN KEY(oidServicio) REFERENCES SERVICIO (oidServicio))");
            ejecutarSQL("CREATE TABLE DETALLE_PEDIDO_PRODUCTO (oidDetallePedidoProducto VARCHAR(36) NOT NULL, descripcion VARCHAR(40), cantidad INTEGER NOT NULL, importeSubtotal DOUBLE, oidPedido VARCHAR(36), oidProducto VARCHAR(36) NOT NULL, PRIMARY KEY(oidDetallePedidoProducto), FOREIGN KEY(oidPedido) REFERENCES PEDIDO (oidPedido), FOREIGN KEY(oidProducto) REFERENCES PRODUCTO (oidProducto))");
            ejecutarSQL("CREATE TABLE HISTORICO_PRECIO (oidHistoricoPrecio VARCHAR(36) NOT NULL, fechaDesde TIMESTAMP NOT NULL, fechaHasta TIMESTAMP, precio DOUBLE NOT NULL, oidServicio VARCHAR(36), oidProducto VARCHAR(36), PRIMARY KEY(oidHistoricoPrecio), FOREIGN KEY(oidServicio) REFERENCES SERVICIO (oidServicio), FOREIGN KEY(oidProducto) REFERENCES PRODUCTO (oidProducto))");
            ejecutarSQL("CREATE TABLE CONFIGURACION (ultimoNroPedido INTEGER )");
            //            ejecutarSQL("CREATE TABLE CONFIGURACION (motorBD VARCHAR(20))");

        } catch (Exception e) {
            System.out.println("Error al inicializar BD: " + e.toString());
        }
    }
}
